import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.List;

public class World extends Canvas implements Runnable {
	private static final long serialVersionUID = 1L;
	List<Guy> typen;
	private Image dbImage;			// Speicher fuer DoubleBuffering
	private Graphics dbGraphics;	// Speicher fuer DoubleBuffering
	Tile[][] tiles;
	Thread th=null;
	List<Level> allLevels;
	Level currentLevel;
	Sazana parent=null;
	int oldkey=0;
	
	public World(Sazana sazana) {
		this.parent=sazana;
		setPreferredSize(new Dimension(1024, 768));
		allLevels = new ArrayList<Level>();	
		typen=new ArrayList<Guy>();
		
		addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if (oldkey!=e.getKeyCode()) {
					if(e.getKeyCode() == 37) {
						parent.out.println("left");
					}
					if(e.getKeyCode() == 38) {
						parent.out.println("up");
					}
					if(e.getKeyCode() == 39) {
						parent.out.println("right");
					}
					if(e.getKeyCode() == 40) {
						parent.out.println("down");
					}
					if (e.getKeyChar()=='s') {
						saveWorld();
					}
					if (e.getKeyCode()==27) {
						System.exit(0);
						parent.out.println("disconnect");
					}
					
					oldkey=e.getKeyCode();
				}
			}
			
			public void keyReleased(KeyEvent e) {
				oldkey=0;
				if(e.getKeyCode() == 37) {
					parent.out.println("stopleft");
				}
				if(e.getKeyCode() == 38) {
					parent.out.println("stopup");
				}
				if(e.getKeyCode() == 39) {
					parent.out.println("stopright");
				}
				if(e.getKeyCode() == 40) {
					parent.out.println("stopdown");
				}
				if (e.getKeyCode()==KeyEvent.VK_ENTER) {
					typeMessage();
				}
//				typ.MoveStop();
			}
		});
		
//		
		Level test = new TestLevel(this);
		test.saveLevel("test4.lvl");
		loadAllLevels();
		LoadLevel(allLevels.get(0));
		
		loadWorld(); // Welt laden
		
		th = new Thread(this);
		th.start();
	}
    
	public void createGuy() {
		Guy guy=new Guy(this, (tiles.length - 1) * 32, (tiles[0].length - 1) * 32);
		guy.PositionX = 64;
		guy.PositionY = 128;
		typen.add(guy);
	}
	public void killGuy(Guy guy)
	{
		for(Guy g : typen)
		{
			if (g == guy)
			{
				typen.remove(g);
				g = null;
			}
		}
		
	}
	
	public void typeMessage() {
		parent.message.requestFocusInWindow();
	}
	
	public void loadAllLevels(){
    	File dir = new File(new java.io.File("").getAbsolutePath());

    	
    	File[] allFiles = dir.listFiles();
    	for (File file : allFiles) {
				if (file.getName().endsWith(".lvl")){
		    		Level temp = new Level(this);
		    		String fileName=file.getName();
					temp.loadLevel(fileName);
					allLevels.add(temp);
			}
		}
    }

	
	public void paint(Graphics g) {
		for (int x = 0; x < tiles.length; x++) {
			for (int y = 0; y < tiles[0].length; y++) {
				if (tiles[x][y] != null)
					tiles[x][y].paint(g, x, y, this);
			}
		}
		for (Guy typ: typen) {
			typ.paint(g, this);
		}
		
		for (int x = 0; x < tiles.length; x++) {
			for (int y = 0; y < tiles[0].length; y++) {
				if (tiles[x][y] != null)
					tiles[x][y].paintCeiling(g, x, y, this);
			}
		}
	}
	
	public void LoadLevel(Level level){
		tiles = new Tile[level.breite][level.hoehe];
		Random rand = new Random();
		
		for (int x = 0; x < tiles.length; x++) {
			for (int y = 0; y < tiles[x].length; y++) {
				Tile t = new Tile();
				if (rand.nextInt(14) == 0)
					t.loadFloor(level.randomFloor, this);
				else
					t.loadFloor(level.standardFloor, this);
				tiles[x][y] = t;
			}
		}
		
		for (LevelObject levelObject : level.levelObjects) {
			for (int x = 0; x < levelObject.object.length; x++) {
				for (int y = 0; y < levelObject.object[x].length; y++) {
					Tile t = levelObject.object[x][y];
					tiles[x + levelObject.startPositionX][y + levelObject.startPositionY] = t;
				}
			}
		}
		for (int x = 0; x < tiles.length; x++) {
			for (int y = 0; y < tiles[x].length; y++) {
				tiles[x][y].reloadImages(this);
			}
		}
		currentLevel = level;
	}
	
	public Level findLeftLevel(){
		for(Level item: allLevels) {
	        if (item.levelID==currentLevel.leftlLevelID) {
	            return item;
	        }
		}
		return null;
	}
	
	public Level findTopLevel(){
		for(Level item: allLevels) {
	        if (item.levelID==currentLevel.toplLevelID) {
	            return item;
	        }
		}
		return null;
	}
	
	public Level findBottomLevel(){
		for(Level item: allLevels) {
	        if (item.levelID==currentLevel.bottomlLevelID) {
	            return item;
	        }
		}
		return null;
	}
		
		public Level findrightLevel(){
			for(Level item: allLevels) {
		        if (item.levelID==currentLevel.rightLevelID) {
		            return item;
		        }
			}
			return null;
		}
	
	public void update(Graphics g)
	{
		//Double-Buffer initialisieren
		if (dbImage == null) {
			dbImage = createImage(this.getWidth(), this.getHeight());
			dbGraphics = dbImage.getGraphics();
		}

		//Hintergrund loeschen
		dbGraphics.setColor(getBackground());
		dbGraphics.fillRect(0, 0, this.getWidth(), this.getHeight());
		//Vordergrund zeichnen
		dbGraphics.setColor(getForeground());
		paint(dbGraphics);
		
		//Offscreen anzeigen
		g.drawImage(dbImage, 0, 0, this);
	}	
	
	public void loadWorld() {
        if ((new File("world.dat")).exists()) {
        	try {
        		FileInputStream fs = new FileInputStream("world.dat");
                ObjectInputStream is = new ObjectInputStream(fs);
                tiles=(Tile[][])is.readObject();
                is.close();
            }
            catch (Exception e) {
            }
        }
        for (int i = 0; i < 32; i++)
        	for (int j = 0; j < 24; j++)
        		tiles[i][j].reloadImages(this);
	}
	
	public void saveWorld() {
		try {
			ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("world.dat"));
			os.writeObject(tiles);
			os.flush();
			os.close();
        	System.out.println("Welt gespeichert!");
		}
        catch(IOException e) {
        	System.out.println("Es ist ein Fehler beim Speichern aufgetreten.");
        }        
	}
	
	public void run() {
		while (th != null) {
			for (Guy typ: typen) {
				typ.clock();
			}
			
			repaint();
			
			try {
				Thread.sleep(35);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
